package com.ys.service.storage.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.dto.AddDto;
import com.ys.entity.base.CheckByGrid;
import com.ys.entity.business.TpProductActive;
import com.ys.entity.flow.YspModel;
import com.ys.entity.hr.ThrOperateCompanyApply;
import com.ys.entity.storage.TccDisassembleByHand;
import com.ys.entity.storage.TccDisassembleByHandItem;
import com.ys.entity.sys.*;
import com.ys.enume.base.TransactionTypeEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.enume.storage.TccStockSourceEnum;
import com.ys.mapper.storage.StorageMapper;
import com.ys.mapper.storage.TccDisassembleByHandItemMapper;
import com.ys.mapper.storage.TccDisassembleByHandMapper;
import com.ys.service.business.TcwAccountDetailedForCompanyService;
import com.ys.service.flow.YspTaskService;
import com.ys.service.storage.TccDisassembleByHandService;
import com.ys.service.storage.TccStockControlService;
import com.ys.util.CheckUtil;
import com.ys.util.ToolUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 手工拆装单
 */
@Service("tccDisassembleByHandService")
public class TccDisassembleByHandServiceImpl implements TccDisassembleByHandService {
	private static final Logger logger = LoggerFactory.getLogger(TccDisassembleByHandServiceImpl.class);

	@Autowired
	private TccDisassembleByHandMapper tccDisassembleByHandMapper;

	@Autowired
	private TccDisassembleByHandItemMapper tccDisassembleByHandItemMapper;

	@Autowired
	private YspTaskService yspTaskService;

	@Autowired
	private StorageMapper storageMapper;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private TccStockControlService tccStockControlService;


	@Autowired
	private TcwAccountDetailedForCompanyService tcwAccountDetailedForCompanyService;


	private final Long GRID = 72L;

	/**
	 * 新增
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R add(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("新增传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TccDisassembleByHand entity = JSON.parseObject(JSON.toJSONString(params), TccDisassembleByHand.class);
		entity.setStatus(1);//状态
		entity.setEffectStock(0);//审批状态

		//获取制单人信息
		TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setStatus(1).queryFirst();
		if(tsUserChange!=null){
			entity.setCreateChangeId(tsUserChange.getId());//制单人变更信息
		}else {
			return R.error("未查询到制单人信息！");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}

		//新增
		tccDisassembleByHandMapper.insert(entity);

		YsMenu ysMenu = new YsMenu().setId(menuId).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, entity.getBid(), createUserId);
		}
		//return R.ok(EditDto.closeAndReload());
		return R.ok(AddDto.gotoEdit("/web/storage/tccDisassembleByHand/toEdit?bid=" + entity.getBid()));
	}


	/**
	 * 修改
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R update(Map<String, Object> params, Long menuId) throws Exception{
		logger.info("修改传参:"+params);
		//参数验证
		String errorBack = checkParams(params, menuId);
		if(errorBack!=null && !"".equals(errorBack)){
			return R.error(errorBack);
		}
		TccDisassembleByHand entity = JSON.parseObject(JSON.toJSONString(params), TccDisassembleByHand.class);
		// 验证状态
		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst == null) {
			return R.error("审批数据不存在，无法编辑");
		}

		//保存列表信息
		R saveItemRes = saveItem(params,entity);
		if(saveItemRes.getCode()==1){
			return saveItemRes;
		}
		tccDisassembleByHandMapper.update(entity);
		return R.ok();
	}


	//保存子列表信息
	public R saveItem(Map<String, Object> params, TccDisassembleByHand entity) throws Exception{
		//保存列表信息
		List<Map<String, Object>> subDataList = new ArrayList<>();
		if(params.get("subData")!=null){
			JSONArray subData = JSON.parseArray(params.get("subData").toString());
			CheckByGrid checkByGrid = checkParamsByGrid(subData,GRID,params);
			if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
				return R.error(checkByGrid.getErrMsg());
			}
			subDataList = checkByGrid.getSubDataList();
		}else {
			return R.error("列表信息为空！");
		}

		//先删除详情数据
		storageMapper.deleteTccDisassembleByHandByHandByPbid(entity.getBid());
		//再新增
		for (int i = 0; i < subDataList.size(); i++) {
			Map<String, Object> item = subDataList.get(i);
			TccDisassembleByHandItem itemInfo = JSON.parseObject(JSON.toJSONString(item), TccDisassembleByHandItem.class);
			itemInfo.setStatus(1);
			itemInfo.setPbid(entity.getBid());
			//新增
			tccDisassembleByHandItemMapper.insert(itemInfo);
		}
		return R.ok();
	}


	//删除
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R del(Long id) throws Exception{
		if (id == null) {
			return R.error("ID不能为空");
		}
		TccDisassembleByHand entity = new TccDisassembleByHand().setId(id).queryFirst();
		if (entity.getEffectStock() == FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("已生效数据无法删除");
		}
		// 验证是否制单人
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setId(entity.getCreateChangeId()).queryFirst();
		if (!tsUserChange.getUserId().equals(loginUserId) && !"admin".equals(loginUserId)) {
			return R.error("非制单人，无法删除");
		}
		//删除
		tccDisassembleByHandMapper.deleteTrue(id);
		//删除列表信息
		storageMapper.deleteTccDisassembleByHandByHandByPbid(entity.getBid());
		//删除流程
		yspTaskService.flowDelete(entity.getBid(), loginUserId);
		return R.ok();
	}



	/**
	 * 流转通过
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowPass(String bid,String loginUserId ) throws Exception {
		//获取单据信息
		TccDisassembleByHand entity = new TccDisassembleByHand().setBid(bid).queryFirst();
		if (entity == null) {
			return R.error("该单据不存在,请核实后再操作!");
		}
		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		Flow f = yspTaskService.flowPass(entity.getBid(),loginUserId);

		if (f.getCode() == Flow.Code.FAILED.value) {
			return R.error(f.getMsg());
		} else {
			// 若是制单流转，冻结库存
			if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
				tccStockControlService.frozen(
						entity.getStockControlId(),
						entity.getDisassembleNum(),
						TccStockSourceEnum.Source.TCC_DisassembleByHand.value,
						entity.getBid(),
						entity.getId()
				);
			}
			if (f.getState() == Flow.State.FINISH.value) {
				return flowFinish(entity);
			}
			return R.ok();
		}
	}

	/**
	 * 流转结束
	 */
	public R flowFinish(TccDisassembleByHand entity) throws Exception {

		YsProcInst ysProcInst = new YsProcInst().setBid(entity.getBid()).queryFirst();
		if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.FINISH.value) {
			return R.error("流程状态有误");
		}
		/*
		if(checkUtil.isNullByObject(entity.getChw())){
			return R.error("请设置入库仓库信息");
		}
		 */

		Date theDate = new Date();
		entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
		entity.setUpdateTime(theDate);

		//获取子表信息
		List<Map<String,Object>> itemList = getItemListByBid(entity.getBid());
		if(itemList == null || itemList.size()<=0){
			return R.error("该单据列表不存在,请核实后再操作!");
		}
		TpProductActive tpProductActive = new TpProductActive().setCode(entity.getProductCode()).queryFirst();
		ThrOperateCompanyApply thrOperateCompanyApply = new ThrOperateCompanyApply().setVgsbm(entity.getVgsbm()).queryFirst();
		//****1、业务流水****
		if(entity.getDisassembleNum()!=null && entity.getDisassembleAmount()!=null){
			if(checkUtil.isNotNullByObject(entity.getVgsbm())){
				BigDecimal totalAmount = entity.getDisassembleAmount().multiply(new BigDecimal(entity.getDisassembleNum()));
				if(totalAmount.compareTo(BigDecimal.ZERO)!=0){
					tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJcNoTrigger(
							entity.getVgsbm(),
							thrOperateCompanyApply.getVgsjc(),
							"GS0608",
							"仓储部",
							TransactionTypeEnum.BusinessType.CCFW_ZZF.name,
							totalAmount.negate(),
							entity.getCreateTime(),
							theDate,
							"手工拆装单："+entity.getBid()+"，"+entity.getProductCode()+"-"+tpProductActive.getName()+"-"+totalAmount,
							entity.getBid(),
							theDate
					);
					tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJcNoTrigger(
							"GS0608",
							"仓储部",
							entity.getVgsbm(),
							thrOperateCompanyApply.getVgsjc(),
							TransactionTypeEnum.BusinessType.CCFW_ZZF.name,
							totalAmount,
							entity.getCreateTime(),
							theDate,
							"手工拆装单："+entity.getBid()+"，"+entity.getProductCode()+"-"+tpProductActive.getName()+"-"+totalAmount,
							entity.getBid(),
							theDate
					);
				}


			}else {
				return R.error("运营公司编码为空，无法产生流水!");
			}
		}

		//****2、母件解冻****
		tccStockControlService.thaw(
				entity.getStockControlId(),
				entity.getDisassembleNum(),//拆装数量
				TccStockSourceEnum.Source.TCC_DisassembleByHand.value,
				entity.getBid(),
				entity.getId()
		);

		//****3、母件出库****
		tccStockControlService.outWithRunning(
				entity.getStockControlId(),
				"组装单号："+entity.getBid(),
				entity.getDisassembleNum(),//拆装数量
				entity.getBid(),
				TccStockSourceEnum.Source.TCC_DisassembleByHand.value,
				entity.getId()
		);

		//遍历详情信息
		for (Map<String,Object> item : itemList){

			//****4、子件 入库生成库存 ****

			BigDecimal subBomAmount = BigDecimal.ZERO;
			if(checkUtil.isNotNullByObject(item.get("subBomAmount"))){
				subBomAmount = new BigDecimal(item.get("subBomAmount").toString());
			}
			tccStockControlService.inWithRunning(
					entity.getBid(),
					item.get("subChw").toString(),
					item.get("subName").toString(),
					new BigDecimal(item.get("storeNum").toString()).intValue(),
					item.get("subCode").toString(),
					new BigDecimal(item.get("storeNum").toString()).intValue(),
					subBomAmount.setScale(2, BigDecimal.ROUND_HALF_UP),
					(subBomAmount.multiply(new BigDecimal(item.get("storeNum").toString()))).setScale(2, BigDecimal.ROUND_HALF_UP),
					BigDecimal.ZERO,
					BigDecimal.ZERO,
					entity.getVgsbm(),
					theDate,
					TccStockSourceEnum.IsParent.NO.value,
					entity.getBid(),TccStockSourceEnum.Source.TCC_DisassembleByHand.value,
					"手工拆装单："+entity.getBid(),
					"C109",
					entity.getBid(),
					entity.getId()
			);
		}

		//修改信息
		tccDisassembleByHandMapper.update(entity);
		return R.ok();

	}



	//流转驳回
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowRefuse(String bid, String reason,String loginUserId) throws Exception{

		R r = yspTaskService.flowRefuse(bid, reason, ShiroUtils.getUserId());

		if (r.getCode() == R.Code.SUCCESS.value) {
			YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
			// 若退回到制单状态，则解冻库存
			if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
				TccDisassembleByHand entity = new TccDisassembleByHand().setBid(bid).queryFirst();
				tccStockControlService.thaw(
						entity.getStockControlId(),
						entity.getDisassembleNum(),
						TccStockSourceEnum.Source.TCC_DisassembleByHand.value,
						entity.getBid(),
						entity.getId()
				);
			}
		}


		return r;
	}



	//流转退回
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowInit(String bid, String reason,String loginUserId) throws Exception{
		R r = yspTaskService.flowInit(bid, reason, ShiroUtils.getUserId());

		if (r.getCode() == R.Code.SUCCESS.value) {
			YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
			// 若退回到制单状态，则解冻库存
			if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
				TccDisassembleByHand entity = new TccDisassembleByHand().setBid(bid).queryFirst();
				tccStockControlService.thaw(
						entity.getStockControlId(),
						entity.getDisassembleNum(),
						TccStockSourceEnum.Source.TCC_DisassembleByHand.value,
						entity.getBid(),
						entity.getId()
				);
			}
		}

		return r;
	}

	@Override
	public Map<String,Object> getExtraParam(String bid) throws Exception{
		return new TccDisassembleByHand()

				.addLeftJoin("YS_ProcInst P ON P.Bid = A.Bid ")
				.addField("FORMAT(P.UpdateTime, 'yyyy-MM-dd HH:mm:ss') AS auditingTime")//审核时间

				.addLeftJoin("TP_ProductActive B ON B.Code = A.ProductCode")//listing库
				.addField("B.Name AS productName")//商品名称

				.addLeftJoin("THR_OperateCompanyApply C ON C.Vgsbm = A.Vgsbm")
				.addField("C.Vgsjc AS vgsjc")//运营公司简称


				.addLeftJoin("TCC_Location D ON D.Chw = A.Chw")//货位信息表
				.addField("D.Vhw AS vhw")//货位
				.addLeftJoin("TCC_WarehouseArea E ON E.Ckq = D.Ckq")//库区
				.addField("E.Vkq AS vkq")//库区
				.addLeftJoin("TCC_Warehouse F ON F.Cck = E.Cck")//仓库
				.addField("F.Vck AS vck")//仓库

				.setBid(bid)
				.queryFirstMap();
	}

	//根据主表bid获取子表信息
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public List<Map<String,Object>> getItemListByBid(String bid) throws Exception {
		//获取子表信息
		return new TccDisassembleByHandItem()

				.addLeftJoin("TP_ProductActiveComponent SB ON SB.Code = A.SubCode")//listing库子件信息
				.addField("SB.Name AS subName")//子件名称
				.addField("SB.Bprice AS subBomAmount")//子件单价

				//.addLeftJoin("TCC_StockControl SC ON SC.Id = A.StockControlId")//库存信息表
				//.addField("SC.PurchasePrice AS purchasePrice")//采购单价

				.addLeftJoin("TCC_Location SD ON SD.Chw = A.SubChw")//货位信息表
				.addField("SD.Vhw AS subVhw")//货位
				.addLeftJoin("TCC_WarehouseArea SE ON SE.Ckq = SD.Ckq")//库区
				.addField("SE.Vkq AS subVkq")//库区
				.addLeftJoin("TCC_Warehouse SF ON SF.Cck = SE.Cck")//仓库
				.addField("SF.Vck AS subVck")//仓库

				.addLeftJoin("TCC_DisassembleByHand G ON G.Bid = A.Pbid")//母表
				.addField("G.ProductCode AS productCode")//母件商品编码

				.setPbid(bid)
				.setOrderby("A.SubCode ASC")
				.queryMap();
	}


	/**
	 * 参数验证
	 */
	public String checkParams(Map<String, Object> params, Long menuId) throws Exception {
		//获取pc字段数据
		List<YsCol> listField = new YsCol()
				.where("A.MenuId = "+menuId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		//验证必填字段的非空；其他字段的长度限制、类型
		String backMsg = checkUtil.checkTableColLengthAndDataType("TCC_DisassembleByHand",listField,params,ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1);
		if(checkUtil.isNotNullByObject(params.get("disassembleNum")) && !checkUtil.isPositiveInteger(params.get("disassembleNum").toString())){
			backMsg = "\"拆装数量\"必须是正整数";
		}
		if(checkUtil.isNotNullByObject(params.get("disassembleNum")) && checkUtil.isNotNullByObject(params.get("chwNum"))){
			if(new BigDecimal(params.get("disassembleNum").toString()).compareTo(new BigDecimal(params.get("chwNum").toString()))>0){
				backMsg = "\"拆装数量\"必须≤\"库存数量\"";
			}

		}
		return backMsg;
	}



	/**
	 * 子表参数验证
	 */
	public CheckByGrid checkParamsByGrid(JSONArray subDataArray, Long gridId,Map<String, Object> params) throws Exception {
		CheckByGrid checkByGrid = new CheckByGrid();
		//获取pc字段数据
		List<YsGridCol> listField = new YsGridCol()
				.setGridId(gridId)
				.setOrderby("A.SortNo ASC")
				.queryList();
		StringBuffer backMsg = new StringBuffer();
		List<Map<String, Object>> subDataList = new ArrayList<>();

		if(subDataArray!=null && subDataArray.size()>0){
			for (int i = 0; i < subDataArray.size(); i++) {
				JSONObject jsonObject = subDataArray.getJSONObject(i);
				Map<String, Object> paramsNewByRecord = new HashMap<>();
				for (String key : jsonObject.keySet()) {
					paramsNewByRecord.put(key, jsonObject.get(key));
				}
				subDataList.add(paramsNewByRecord);
			}
			//验证
			for(int i = 0;i<subDataList.size();i++){
				StringBuffer backMsgByRow = new StringBuffer();
				Map<String, Object> subData = subDataList.get(i);
				//验证必填字段的非空；其他字段的长度限制、类型
				backMsgByRow.append(checkUtil.checkTableColLengthAndDataTypeByGrid(
						"TCC_DisassembleByHandItem",
						listField,
						subData,
						ysColItem->
								ysColItem.getCode().equals("subDisNum")
										|| ysColItem.getCode().equals("subChw")
										|| ysColItem.getCode().equals("subCode")
										|| ysColItem.getCode().equals("storeNum")
				));
				if(checkUtil.isNotNullByObject(subData.get("subDisNum")) && !checkUtil.isPositiveInteger(subData.get("subDisNum").toString())){
					backMsgByRow.append("\"子件拆装数量\"必须是正整数；");
				}
				if(checkUtil.isNotNullByObject(subData.get("storeNum")) && !checkUtil.isPositiveInteger(subData.get("storeNum").toString())){
					backMsgByRow.append("\"子件入库数量\"必须是正整数；");
				}
				//验证母件商品编码
				if(checkUtil.isNotNullByObject(subData.get("productCode")) && checkUtil.isNotNullByObject(params.get("productCode"))){
					if(!subData.get("productCode").toString().equals(params.get("productCode").toString())){
						backMsgByRow
								.append("子件编码：")
								.append(checkUtil.isNotNullByObject(subData.get("subCode"))?subData.get("subCode").toString():"")
								.append("该子件不属于所选的母件商品；");
					}
				}

				if(checkUtil.isNotNullByObject(backMsgByRow)){
					backMsg.append("列表第")
							.append((i+1))
							.append("行，")
							.append(backMsgByRow)
							.append("；");
				}
			}

			//验证：入库数量总计需要等于拆装数量
			//根据子件编码去重
			List<Map<String, Object>> subDataListByGroup = ToolUtil.groupsByList(subDataList,e->e.get("subCode")!=null?e.get("subCode").toString():"");
			for(Map<String, Object> item:subDataListByGroup){
				String subCode = item.get("subCode").toString();
				List<Map<String, Object>> subDataListBySubCode = subDataList.stream()
						.filter(e->e.get("subCode")!=null && e.get("subCode").toString().equals(subCode))
						.collect(Collectors.toList());
				//子件拆装数量
				BigDecimal subDisNum = checkUtil.isNotNullByObject(item.get("subDisNum"))?new BigDecimal(item.get("subDisNum").toString()):BigDecimal.ZERO;
				BigDecimal storeNumTotal = BigDecimal.ZERO;//入库数量
				for(Map<String, Object> countitem:subDataListBySubCode){
					if(checkUtil.isNotNullByObject(countitem.get("storeNum"))){
						storeNumTotal = storeNumTotal.add(new BigDecimal(countitem.get("storeNum").toString()));
					}
				}
				if(subDisNum.compareTo(storeNumTotal)!=0){
					backMsg.append("子件编码：")
							.append(subCode)
							.append("，入库数量总计需要等于拆装数量");
				}

			}

		}else{
			backMsg = new StringBuffer("列表信息为空");
		}
		checkByGrid.setErrMsg(backMsg.toString());
		checkByGrid.setSubDataList(subDataList);

		return checkByGrid;
	}






}
